#ifndef CLIENT_HPP
#define CLIENT_HPP

#include <boost/asio.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/signals2.hpp>
#include <stdint.h>
#include <boost/array.hpp>

#include "logger.hpp"
#include "message_receiver.hpp"

class web_socket_server;

class client :
    public boost::enable_shared_from_this<client>
{
public:
    client(boost::asio::io_service& io_service, web_socket_server* server, boost::shared_ptr<logger> log, uint64_t index);
    ~client() { std::cout << "client removed" << std::endl; }

    inline boost::asio::ip::tcp::socket& socket() { return _socket; }
    inline web_socket_server* server() { return _server; }
    const inline uint64_t& index() const { return _index; }
    inline boost::signals2::signal<void (boost::shared_ptr<client>)>& disconnected() { return _disconnected; }
    void set_receiver(message_receiver* new_receiver) { _receiver = new_receiver; }

    void start();
    void send(const std::wstring& message);

private:
    boost::asio::ip::tcp::socket _socket;
    web_socket_server* _server;
    boost::shared_ptr<logger> _logger;
    std::string _message;
    boost::array<char, 1024> _buf;
    uint64_t _index;
    boost::signals2::signal<void (boost::shared_ptr<client>)> _disconnected;
    message_receiver* _receiver;

    void handle_write(const boost::system::error_code& error, size_t bytes_transferred);
    void handle_shake(const boost::system::error_code& error, std::size_t bytes_transferred);
    void handle_read(const boost::system::error_code& error, std::size_t bytes_transferred);
    void disconnect();
};

#endif // CLIENT_HPP
